﻿using System.Text;
using System.Windows;
using personalplaner.business.extensions;
using personalplaner.common.mvvm;
using System.Collections.Generic;
using personalplaner.business.stamm;
using personalplaner.common.mvvm.mediator;
using personalplaner.gui.common;
using personalplaner.servicemodel.dataaccess;
using System.Collections.ObjectModel;
using System.Windows.Input;
using personalplaner.common.mvvm.commands;
using personalplaner.gui.stamm.windows;
using personalplaner.business.enums;
using System.Linq;
using personalplaner.gui.stamm.views;
using personalplaner.business;

namespace personalplaner.gui.stamm.viewmodels
{
	public class PlanLayoutStammViewModel : BaseViewModel
	{
		public PlanLayoutStammViewModel(DependencyObject parent)
			: base(parent)
		{
		}

        #region Mediator Messages

        [MediatorMessageSink("SettingsRefresh")]
        public void SettingsRefresh()
        {
            if (SelectedPlanLayout == null)
                return;

            var da = GetService<IOptionsDataAccess>();

            foreach (var layout in SelectedPlanLayout)
                layout.ShowPrsId = da.ShowPrsId;
        }

        [MediatorMessageSink("SchemaDeleted", ParameterType = typeof(int))]
        public void SchemaDeleted(int schemaId)
        {
            _planLayouts = null;
            RaisePropertyChanged("PlanLayouts");
        }

        #endregion

        #region Implementation

        public void SetSinglePlanSchema(int schemaid)
        {
            var da = GetService<IPlanSchemaDataAccess>();
			var itm = da.GetSchema(schemaid);

            PlanLayouts.Clear();
            IsSingleItem = true;

            if (itm == null)
                return;

            // set the status to active so that it won't be drawn red
            itm.Status = enStatus.Active;

            PlanLayouts.Add(itm);
            ActiveListItem = itm;
        }

		public override void Loaded()
		{
			var mw = GetService<IMainWindowDisplayContainer>();
			mw.IsWaitVisible = false;
		}

		public override void Unload()
		{
			ActiveListItem = null;
		}

		internal void ModeItemTo(PlanSchemaItem data, int index)
		{
			if (index < 0)
				return;

			if (data == null || data.RowType == enPlanRowType.Abteilung)
				return;

			if (SelectedPlanLayout.IndexOf(data) == index)
				return;

			// check if the item is the max or min item
			// get the max index of the abteilung
			var max = (from a in SelectedPlanLayout
					   where a.AbteilungID == data.AbteilungID && a.RowType != enPlanRowType.Abteilung
					   select a).ToList().Max(a => a.PersonSchemaID) - 1;

			// get the max index of the abteilung
			var min = (from a in SelectedPlanLayout
					   where a.AbteilungID == data.AbteilungID && a.RowType != enPlanRowType.Abteilung
					   select a).ToList().Min(a => a.PersonSchemaID) - 1;

			if ((SelectedPlanLayout.IndexOf(data) == max && index >= max) || (SelectedPlanLayout.IndexOf(data) == min && index <= min))
				return;


			// reposition the item
			SelectedPlanLayout.Remove(data);

			// get the max index of the abteilung
			max = (from a in SelectedPlanLayout
					   where a.AbteilungID == data.AbteilungID && a.RowType != enPlanRowType.Abteilung
						 select a).ToList().Max(a => a.PersonSchemaID) - 1;

			// get the max index of the abteilung
			min = (from a in SelectedPlanLayout
					   where a.AbteilungID == data.AbteilungID && a.RowType != enPlanRowType.Abteilung
						 select a).ToList().Min(a => a.PersonSchemaID) - 1;

			// corect the index
			if (index < min)
				index = min;
			if (index > max)
				index = max;

			SelectedPlanLayout.Insert(index, data);
			// reset the indexes
			index = 1;
			foreach (var itm in SelectedPlanLayout)
			{
				itm.PersonSchemaID = index;
				index++;
			}
		}

		#endregion

		#region Commands

		#region Custom Commands

		ICommand _addpersoncommand;
		public ICommand AddPersonCommand
		{
			get
			{
				if (_addpersoncommand == null)
					_addpersoncommand = new RelayCommand(OnAddPerson, parameter => SelectedPlanLayout != null && SelectedPlanLayout.Count > 0);
				return _addpersoncommand;
			}
		}

		private void OnAddPerson(object parameter)
		{
            var lst = from a in SelectedPlanLayout
                      where a.RowType == enPlanRowType.Abteilung
                      select new Abteilung
                      {
                          AbteilungID = a.AbteilungID,
                          Name = a.AbteilungName
                      };

            var wnd = new AddPersonToSchema(lst, SelectedPlanLayout);
            wnd.Owner = Window.GetWindow(Parent);
			if (wnd.ShowDialog() == false)
				return;

			PlanSchemaItem item;
			if (wnd.IsEmptyRow)
			{
				var abt = wnd.SelectedAbteilung;
				// create an empty row
				item = new PlanSchemaItem
				{
					AbteilungID = abt.AbteilungID,
					RowType = enPlanRowType.None
				};
			}
			else
			{
				// create the row for the person
				var abt = wnd.SelectedAbteilung;
				var pers = wnd.SelectedPerson;
                var options = GetService<IOptionsDataAccess>();

				item = new PlanSchemaItem
				       {
				       	AbteilungID = abt.AbteilungID,
				       	AbteilungName = abt.Name,
				       	PrsID = pers.PrsID,
				       	Vorname = pers.Name,
				       	Nachname = pers.Nachname,

                        ShowPrsId = options.ShowPrsId,
                        NameDisplay = options.NameDisplayOption
				       };
			}

			// get the max index of the abteilung
			var index = (from a in SelectedPlanLayout 
					  where a.AbteilungID == wnd.SelectedAbteilung.AbteilungID 
					  select a).ToList().Max(a => a.PersonSchemaID);

			SelectedPlanLayout.Insert(index, item);

			// reset the indexes
			index = 1;
			foreach (var itm in SelectedPlanLayout)
			{
				itm.PersonSchemaID = index;
				index++;
			}

		}


		ICommand _addabteilungcommand;
		public ICommand AddAbteilungCommand
		{
			get
			{
				if (_addabteilungcommand == null)
					_addabteilungcommand = new RelayCommand(OnAddAbteilung, parameter => SelectedPlanLayout != null);
				return _addabteilungcommand;
			}
		}

		private void OnAddAbteilung(object parameter)
		{
			var wnd = new AddAbteilungToSchema();
			wnd.Owner = Window.GetWindow(Parent);

            var abteilungen = (from a in SelectedPlanLayout
                      where a.RowType == enPlanRowType.Abteilung
                      select new Abteilung
                      {
                          AbteilungID = a.AbteilungID,
                          Name = a.AbteilungName
                      }).ToList();

			if (abteilungen.Count() > 0)
				wnd.AbteilungenZugeteilt = abteilungen;

			if (wnd.ShowDialog() == false)
				return;

			var existingItems = SelectedPlanLayout.ToList();
			if (wnd.AbteilungenZugeteilt.Count > 0)
				SelectedPlanLayout.Clear();

			var da = GetService<IPlanSchemaDataAccess>();
			foreach (var abt in wnd.AbteilungenZugeteilt)
			{
				var lst = from psi in existingItems where psi.AbteilungID == abt.AbteilungID select psi;
				if (lst.Count() == 0)
					lst = da.GetPersonenInAbteilung(abt.AbteilungID);

				foreach (var itm in lst)
				{
					SelectedPlanLayout.Add(itm);
				}
			}

			int index = 1;
			foreach(var itm in SelectedPlanLayout)
			{
				itm.PersonSchemaID = index;
				index++;
			}
		}

		ICommand _delrowcommand;
		public ICommand DeleteRowCommand
		{
			get
			{
                if (_delrowcommand == null)
                    _delrowcommand = new RelayCommand<PlanSchemaItem>(OnDeleteRow, parameter => SelectedPlanLayout != null && parameter != null && parameter.RowType != enPlanRowType.Abteilung);
				return _delrowcommand;
			}
		}

		private void OnDeleteRow(PlanSchemaItem parameter)
		{
			SelectedPlanLayout.Remove(parameter);

			int index = 1;
			foreach (var itm in SelectedPlanLayout)
			{
				itm.PersonSchemaID = index;
				index++;
			}
		}

		ICommand _addservicescommand;
		public ICommand AddServicesCommand
		{
			get
			{
				if (_addservicescommand == null)
					_addservicescommand = new RelayCommand(OnAddServices, parameter => SelectedPlanLayout != null);
				return _addservicescommand;
			}
		}

		private void OnAddServices(object parameter)
		{
			var adtl = new AddDiensteToLayout(ActiveListItem.SchemaID);
			var sh = GetService<IMainWindowDisplayContainer>();
			sh.AddSimpleContentItem(enDisplayItemType.AddDienstToLayout, adtl, true);
		}

		ICommand _changestatuscommand;
		public ICommand ChangeStatusCommand
		{
			get
			{
				if (_changestatuscommand == null)
					_changestatuscommand = new RelayCommand(OnchangeStatus, parameter => ActiveListItem != null);
				return _changestatuscommand;
			}
		}

		private void OnchangeStatus(object parameter)
		{
			var da = GetService<IPlanSchemaDataAccess>();
			da.UpdateSchemaStatus(ActiveListItem.SchemaID, ActiveListItem.Status == enStatus.Active ? false : true);

			// refresh the list
			_planLayouts = null;
			RaisePropertyChanged("PlanLayouts");
		}

		#endregion

		#region Stammbar

		ICommand _newcommand;
		public ICommand NewCommand
		{
			get
			{
				if (_newcommand == null)
					_newcommand = new RelayCommand(OnNew);
				return _newcommand;
			}
		}

		private void OnNew(object parameter)
		{
			//ActiveListItem = null;
			ActiveListItem = new PlanSchema();
			SelectedPlanLayout = new ObservableCollection<PlanSchemaItem>();
		}

		ICommand _copycommand;
		public ICommand CopyCommand
		{
			get
			{
				if (_copycommand == null)
					_copycommand = new RelayCommand(OnCopy, parameter => ActiveListItem != null && !ActiveListItem.IsNew);
				return _copycommand;
			}
		}

		private void OnCopy(object parameter)
		{
			int schemaid = ActiveListItem.SchemaID;
			var nps = new PlanSchema()
			{
				Name = ActiveListItem.Name
			};

			ActiveListItem = nps;

			var da = GetService<IPlanSchemaDataAccess>();
			var lst = da.GetPlanSchema(schemaid);
			SelectedPlanLayout = lst != null ? new ObservableCollection<PlanSchemaItem>(lst) : null;
		}
		
		ICommand _okcommand;
		public ICommand OkCommand
		{
			get
			{
				if (_okcommand == null)
					_okcommand = new RelayCommand(OnOkCommand);
				return _okcommand;
			}
		}

		private void OnOkCommand(object parameter)
		{
			//TODO: implement save if changed
			var mw = GetService<IMainWindowDisplayContainer>();
			mw.MoveToPreviousView();
		}

		ICommand _cancelcommand;
		public ICommand CancelCommand
		{
			get
			{
				if (_cancelcommand == null)
					_cancelcommand = new RelayCommand(OnCancelCommand);
				return _cancelcommand;
			}
		}

		private void OnCancelCommand(object parameter)
		{
			var mw = GetService<IMainWindowDisplayContainer>();
			mw.MoveToPreviousView();
		}

        ICommand _deleteCommand;
        public ICommand DeleteCommand
        {
            get
            {
                if (_deleteCommand == null)
                    _deleteCommand = new RelayCommand(OnDelete, param => ActiveListItem != null && !ActiveListItem.IsNew && !IsSingleItem);
                return _deleteCommand;
            }
        }

        private void OnDelete(object parameter)
        {
            if (MessageBox.Show(string.Format(Properties.Resources.DeletePlanlayoutQuestion, ActiveListItem.Name), Properties.Resources.DeletePlanlayout, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
                return;

            var da = GetService<IPlanSchemaDataAccess>();
            var plaene = da.GetPlaeneFromSchemaId(ActiveListItem.SchemaID);
            if (plaene != null && plaene.Any())
            {
                var name = new StringBuilder();
                foreach (var p in plaene)
                    name.AppendLine(string.Format("   - {0}", p.Name));

                MessageBox.Show(string.Format(Properties.Resources.DeleteSchemaPlanExiststToSchemaFormat, name), Properties.Resources.DeletePlanlayout, MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            if (da.DeleteSchema(ActiveListItem.SchemaID))
            {
                var options = GetService<IOptionsDataAccess>();
                if (options.ResetLastSchemaOnDeleteSchema)
                {
                    var layouts = da.GetSchemas(false);
                    if (layouts == null || !layouts.Any())
                    {
                        layouts = da.GetSchemas(true);
                        if (layouts != null && layouts.Any())
                        {
                            // reactivate a schema
                            var schemaid = layouts.Max(l => l.SchemaID);
                            da.UpdateSchemaStatus(schemaid, true);
                        }
                    }
                }
            }
            else
                MessageBox.Show(Properties.Resources.ErrorWhileDeletingSchema, Properties.Resources.DeletePlanlayout, MessageBoxButton.OK, MessageBoxImage.Error);

            _planLayouts = null;
            RaisePropertyChanged("PlanLayouts");
        }

		ICommand _savecommand;
        public ICommand SaveCommand
        {
            get
            {
                if (_savecommand == null)
					_savecommand = new RelayCommand(OnSave, p => ActiveListItem != null);
                return _savecommand;
            }
        }

		private void OnSave(object parameter)
		{
            // reset so that changed is false again
            if (SelectedPlanLayout != null)
            {
                _selectedPlanLayoutCopy = new List<PlanSchemaItem>();
                foreach (var itm in _selectedPlanLayout)
                    _selectedPlanLayoutCopy.Add(itm.Clone());
            }
            else
                _selectedPlanLayoutCopy = null;

			if (SelectedPlanLayout.Count <= 0)
				return;

			var da = GetService<IPlanSchemaDataAccess>();

			int schemaid = ActiveListItem.SchemaID;

			if (ActiveListItem.IsNew)
			{
				if (!string.IsNullOrEmpty(ActiveListItem.Name))
				{
					schemaid = da.CreateNewSchema(ActiveListItem.Name);
                    ActiveListItem.SchemaID = schemaid;
                    ActiveListItem.ID = schemaid;

                    PlanLayouts.Add(ActiveListItem);
				}
				else
				{
					MessageBox.Show("Es ist kein Name für das Schema vorhanden.", "Kein Name", MessageBoxButton.OK, MessageBoxImage.Exclamation);
					RaiseMoveFocus("Name");
					return;
				}
			}
			else
				da.DeleteRowsFromSchema(schemaid);

			if (schemaid <= 0)
			{
				MessageBox.Show(Window.GetWindow(Parent), "Es ist ein Fehler beim erstellen des Schemas aufgetrete.\nEs konnte kein Schema erstellt werden.", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
				return;
			}

			// save the rows
			foreach (var itm in SelectedPlanLayout)
			{
				da.SaveSchemaRow(schemaid, itm);
			}

			// if this dialog was called from the DienstPlanViewModel (Menu edit planlayout)
			// then send the message to all DienstPlanViewModel's so that the one with the schemaid can update itsself
			if (IsSingleItem)
				Mediator.NotifyColleagues<int>("ReloadPlan", schemaid);
		}

		#endregion

		#endregion

		#region Properties

		IList<PlanSchema> _planLayouts;
		public IList<PlanSchema> PlanLayouts
		{
			get
			{
				if (_planLayouts == null)
				{
					var da = GetService<IPlanSchemaDataAccess>();
					var lst = da.GetSchemas(ShowInactive);
					_planLayouts = lst != null ? new ObservableCollection<PlanSchema>(lst) : new ObservableCollection<PlanSchema>();

                    if (_planLayouts != null && _planLayouts.Count > 0)
                        ActiveListItem = _planLayouts[0];
				}
				return _planLayouts;
			}
		}

		bool _showInactive;
		public bool ShowInactive
		{
			get { return _showInactive; }
			set
			{
				_showInactive = value;
				RaisePropertyChanged("ShowInactive");

				_planLayouts = null;
				RaisePropertyChanged("PlanLayouts");
			}
		}


		PlanSchema _activeListItem;
		public PlanSchema ActiveListItem
		{
			get { return _activeListItem; }
			set
			{
                if (Changed)
                {
                    if (MessageBox.Show(Properties.Resources.DieDatenWurdenVeraendertWollenSieSpeichern, Properties.Resources.Save, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                    {
                        OnSave(null);
                    }
                }

				_activeListItem = value;
				RaisePropertyChanged("ActiveListItem");

				RaisePropertyChanged("IsAktivieren");

				if (value == null)
				{
					SelectedPlanLayout = null;
					return;
				}

				var da = GetService<IPlanSchemaDataAccess>();
				var lst = da.GetPlanSchema(value.SchemaID);
				SelectedPlanLayout = lst != null ? new ObservableCollection<PlanSchemaItem>(lst) : null;
			}
		}

        private bool Changed
        {
            get
            {
                if (_selectedPlanLayoutCopy == null && _selectedPlanLayout == null)
                    return false;

                if ((_selectedPlanLayoutCopy == null && _selectedPlanLayout != null) || (_selectedPlanLayoutCopy != null && _selectedPlanLayout == null))
                    return true;

                if (_selectedPlanLayoutCopy.Count != _selectedPlanLayout.Count)
                    return true;

                for (int i = 0; i < _selectedPlanLayout.Count; i++)
                {
                    if (_selectedPlanLayout[i].PrsID != _selectedPlanLayoutCopy[i].PrsID)
                        return true;
                }

                return false;
            }
        }

        IList<PlanSchemaItem> _selectedPlanLayoutCopy;
		IList<PlanSchemaItem> _selectedPlanLayout;
		public IList<PlanSchemaItem> SelectedPlanLayout
		{
			get
			{
				return _selectedPlanLayout;
			}
			set
			{
				_selectedPlanLayout = value;
				RaisePropertyChanged("SelectedPlanLayout");

                if (value != null)
                {
                    _selectedPlanLayoutCopy = new List<PlanSchemaItem>();
                    foreach (var itm in _selectedPlanLayout)
                        _selectedPlanLayoutCopy.Add(itm.Clone());
                }
                else
                    _selectedPlanLayoutCopy = null;
			}
		}

        PlanSchemaItem _selectedPlanlayoutItem;
        public PlanSchemaItem SelectedPlanlayoutItem
        {
            get
            {
                return _selectedPlanlayoutItem;
            }
            set
            {
                _selectedPlanlayoutItem = value;
                RaisePropertyChanged("SelectedPlanlayoutItem");
            }
        }

		public bool IsAktivieren
		{
			get
			{
				if (ActiveListItem == null)
					return false;

				return ActiveListItem.Status == enStatus.Inactive;
			}
		}

        bool _isSingleItem;
        public bool IsSingleItem
        {
            get
            {
                return _isSingleItem;
            }
            set
            {
                _isSingleItem = value;
                RaisePropertyChanged("IsSingleItem");
            }
        }

		#endregion
	}
}
